﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using WindowsFormsApplication4.ServiceReference1;

namespace TravianAutoGUI
{
    public partial class Travian : Form
    {
        TravianLib.Player player_;
        public TravianLib.VillageNew vil;
        //private TravianLib.database _requirements;
        private void login(TravianLib.HTTPFetch htp) {
            htp.NewHttpRequest += new TravianLib.HTTPFetch.HttpRequestEventHandler(PrintHTTPRequest);
            player_ = null;
            player_ = new TravianLib.Player(comboBox2.Text, htp);
            if (player_.Villages.Count > 0)
            {
                vil = player_.Villages[0];
                vil.BuildingComplete += new EventHandler(PrintCurrentBuilding);
                vil.BuildingStarted += new EventHandler(PrintCurrentBuilding);
                drawBuildings();
                Login.SelectedTab = Dorf;
                timer1.Interval = 10000;
                timer1.Enabled = true;
                timer1_Tick(this,new EventArgs());
                PrintCurrentBuilding(this, new EventArgs());

                BindingSource bs = new BindingSource();
                bs.DataSource = vil.Barracks.Targets;
                dataGridView1.AutoGenerateColumns = true;
                dataGridView1.DataSource = bs;
                dataGridView1.AutoResizeColumns();
            }
        }

        private void PrintHTTPRequestCallBack(System.Net.HttpWebRequest wr)
        {
            ListViewItem LI = new ListViewItem(DateTime.Now.ToString());
            LI.SubItems.Add(wr.Method + " " + wr.Address.AbsoluteUri);
            this.listView2.Items.Add(LI);
            this.listView2.EnsureVisible(this.listView2.Items.Count - 1);
            this.listView2.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
            this.listView2.Refresh();
        }
        public delegate void PrintHTTPRequestDelegate(System.Net.HttpWebRequest wr);
        protected virtual void PrintHTTPRequest(System.Net.HttpWebRequest wr)
        {
            listView2.Invoke(new PrintHTTPRequestDelegate(PrintHTTPRequestCallBack), new object[] { wr });
        }
        private void PrintCurrentBuildingCallBack()
        {
            if (vil.Queue.Count() > 0)
            {
                TravianLib.building bd = vil.Queue.ElementAt(0).building;
                lblBuilding.Text = "Building: " + bd.GID.ToString() + " " + bd.Level.ToString();
            }
            else
            {
                lblBuilding.Text = "Building: Nothing";
            }
        }
        public delegate void PrintCurrentBuildingDelegate();
        protected virtual void PrintCurrentBuilding(object sender, EventArgs e)
        {
          lblBuilding.Invoke(new PrintCurrentBuildingDelegate(PrintCurrentBuildingCallBack));
        }
        public Travian()
        {
            try
            {
                InitializeComponent();
                this.CreateHandle();
                listView2.Columns.Add("date");
                listView2.Columns.Add("text");


                dataGridView2.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader;
                dataGridView3.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader;

                // comboBox1.SelectedIndex = 0;
                string[] filePaths = Directory.GetFiles(Application.StartupPath);
                var q = (from c in filePaths
                         where c.EndsWith(".conf")
                         select c.Replace(".conf", ""));

                if (q.Count() > 0)
                {
                    System.Net.CookieCollection cookies = new System.Net.CookieCollection();
                    foreach (string user in q)
                    {
                        comboBox2.Items.Add(Path.GetFileName(user));
                    }
                    comboBox2.SelectedIndex = comboBox2.Items.Count - 1;
                    System.Data.DataSet ds = new DataSet();
                    ds.ReadXml(comboBox2.Text + ".conf");
                    TravianLib.HTTPFetch htp = null;
                    foreach (DataRow tmp in ds.Tables["settings"].Rows)
                    {
                        if (tmp[0].ToString() == "username")
                        {

                        }
                        else if (tmp[0].ToString() == "password")
                        {
                            textBox2.Text = tmp[1].ToString();
                        }
                        else if (tmp[0].ToString() == "server")
                        {
                            comboBox1.Text = tmp[1].ToString();
                        }
                        else
                        {
                            cookies.Add(new System.Net.Cookie(tmp[0].ToString(), tmp[1].ToString()));
                        }
                    }
                    htp = new TravianLib.HTTPFetch(comboBox2.Text, textBox2.Text, comboBox1.Text, cookies);
                    login(htp);

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }        
        }        
        private void button2_Click(object sender, EventArgs e)
        {
            drawBuildings();
        }
        private void drawBuildings()
        {
            listView1.Items.Clear();
            listView3.Items.Clear();
            TravianLib.resources production = vil.ProductionWithQueue;
            if (!vil.BusyBuilding)
            {
                lblQueueTime.Text = "Queue finished: " + vil.QueueFinishTime.ToString();
            }
            var buildings = (from c in vil.BuildingsWithQueue where (int)c.GID < 100
                             orderby c.GID descending
                             select c);
            foreach (TravianLib.building bd in vil.AvaibleBuildings)
            {
                ListViewItem tmp = buildingToListViewItem(bd);
                if (bd.enoughFoodToUpgrade(production) == true)
                {
                    tmp.BackColor = Color.LightGreen;
                }
                else
                {
                    tmp.BackColor = Color.Salmon;
                }
                listView1.Items.Add(tmp);
            }
            foreach (TravianLib.building bd in buildings)
            {
                ListViewItem tmp = buildingToListViewItem(bd);
                if (bd.enoughFoodToUpgrade(production) == true)
                {
                    tmp.BackColor = Color.LightGreen;
                }
                else
                {
                    tmp.BackColor = Color.Salmon;
                }
                listView1.Items.Add(tmp);  
            }
            foreach (TravianLib.queueItem bd in vil.Queue)
            {
                ListViewItem tmp = buildingToListViewItem(bd.building);
                tmp.SubItems.Add(bd.order.ToString());
                tmp.SubItems.Add(bd.resourceWaitTime.ToString());
                tmp.SubItems.Add(bd.ID.ToString());
                tmp.Tag = bd;
                listView3.Items.Add(tmp);
            }
        }
        private ListViewItem buildingToListViewItem(TravianLib.building bd)
        {
            ListViewItem LI = new ListViewItem(bd.GID.ToString());
            LI.SubItems.Add(bd.Level.ToString());
            LI.SubItems.Add(bd.ID.ToString());
            try
            {
                LI.ImageIndex = (int)bd.GID - 1;
            }
            catch
            {
                LI.ImageIndex = 1;
            }
            LI.Tag = bd;           
            return LI;
        }

        private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (((ListView)sender).SelectedItems.Count == 1)
            {
                TravianLib.building bd = ((TravianLib.building)((ListView)sender).SelectedItems[0].Tag);

                // System.Timers.Timer doQueue = new System.Timers.Timer();
                // doQueue.Interval = _requirements.whenCanBuild(vil.baseBuildings_, bd, int.Parse(label4.Tag.ToString()), int.Parse(label6.Tag.ToString()), int.Parse(label5.Tag.ToString()), int.Parse(label7.Tag.ToString())) * 3600 + 60;
                // doQueue.Elapsed += new System.Timers.ElapsedEventHandler(DoQueueEvent);
                // doQueue.AutoReset = false;
                //doQueue.Start();
                vil.addToQueue(bd);
                drawBuildings();
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
           
        }
        private List<System.Windows.Forms.Timer> timers_ = new List<System.Windows.Forms.Timer>();
        private void button4_Click(object sender, EventArgs e)
        {
            //timer2.Interval = (int)vil.barracks.Attack().TotalMilliseconds * 2;
            //timer2.Tick += new EventHandler(timer2_Tick);
            //timer2.Enabled = true;
        }
  
        void timer2_Tick(object sender, EventArgs e)
        {

            if (checkBoxSend.Checked)
            {
                System.Windows.Forms.Timer curTimer = sender as System.Windows.Forms.Timer;
                List<TimeSpan> result = vil.Barracks.Attack((int)this.numericUpDownSquadSize.Value);

                foreach (TimeSpan item in result)
                {
                    System.Windows.Forms.Timer newTimer = new System.Windows.Forms.Timer();
                    newTimer.Enabled = false;
                    timers_.Add(newTimer);
                    newTimer.Interval += (int)item.TotalMilliseconds * 2;
                    newTimer.Tick += new EventHandler(timer2_Tick);
                    newTimer.Enabled = true;
                }
                curTimer.Enabled = false;
                timers_.Remove(curTimer);

                if (timers_.Count == 0 && result.Count == 0)
                {
                    System.Windows.Forms.Timer newTimer = new System.Windows.Forms.Timer();
                    newTimer.Enabled = false;
                    timers_.Add(newTimer);
                    newTimer.Interval += 60000;
                    newTimer.Tick += new EventHandler(timer2_Tick);
                    newTimer.Enabled = true;
                }
            }
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            TravianLib.HTTPFetch htp = new TravianLib.HTTPFetch(comboBox2.Text, textBox2.Text, comboBox1.Text);
            login(htp);            
        }

        private void listView3_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (((ListView)sender).SelectedItems.Count == 1)
            {
                TravianLib.building bd = ((TravianLib.queueItem)((ListView)sender).SelectedItems[0].Tag).building;
                vil.removeFromQeueu(bd);
                drawBuildings();
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                drawResources();
                if (checkBoxBuild.Checked)
                {

                }
                else if (chkResourceFields.Checked)
                {
                    if (vil.buildResourceFields())
                    {
                        PrintCurrentBuilding(this, new EventArgs());
                    }
                }
                else if (vil.doQeueu() && vil.Queue.Count() != 0)
                {

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        private void drawResources()
        {
            TravianLib.resources current = vil.Resources;
            TravianLib.resources production = vil.Production;

            lblClay.Text = current.clay + " (" + production.clay + ")";
            lblWood.Text = current.wood + " (" + production.wood + ")";
            lblIron.Text = current.iron + " (" + production.iron + ")";
            lblCrop.Text = current.crop + " (" + production.crop + ")";
        }

        private void btnUp_Click(object sender, EventArgs e)
        {
            if (listView3.SelectedItems.Count == 1)
            {
                TravianLib.queueItem qi = (TravianLib.queueItem)listView3.SelectedItems[0].Tag;
                vil.moveUpInQueue(qi);
                drawBuildings();
            }
        }

        private void btnDown_Click(object sender, EventArgs e)
        {
            if (listView3.SelectedItems.Count == 1)
            {
                TravianLib.queueItem qi = (TravianLib.queueItem)listView3.SelectedItems[0].Tag;
                vil.moveDownInQueue(qi);               
                drawBuildings();
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            vil.optimizeQueue(lblBuilding);
            drawBuildings();
        }

        private void lblBuilding_TextChanged(object sender, EventArgs e)
        {
            Application.DoEvents();
        }

        private void listView1_MouseMove(object sender, MouseEventArgs e)
        {
            ListViewItem LI = ((ListView)sender).GetItemAt(e.X, e.Y);
            if (LI != null)
            {
                TravianLib.building bd = (TravianLib.building)LI.Tag;
                TravianLib.resources tmp = new TravianLib.resources();
                tmp = bd.UpgradeCosts;
                LI.ToolTipText = "W:" + tmp.wood + " C:" + tmp.clay + " I:" + tmp.iron + " C:" + tmp.crop;
            }
        }

        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            vil.CropOffset = (int)((numericUpDown1)).Value;
        }

        private void tabPage2_Enter(object sender, EventArgs e)
        {

        }

        private void notifyIcon1_DoubleClick(object sender, MouseEventArgs e)
        {
            Show();
            WindowState = FormWindowState.Normal;
        }
        private void Travian_Resize(object sender, EventArgs e)
        {
            if (FormWindowState.Minimized == WindowState)
                Hide();
        }

        private void dataGridView1_RowEnter(object sender, DataGridViewCellEventArgs e)
        {
            DataGridViewRow row =  dataGridView1.Rows[e.RowIndex];
           
            if (!row.IsNewRow)
            {
                Service1SoapClient webReq = new Service1SoapClient();
                Village selected = webReq.getVillageByXY((int)row.Cells[0].Value, (int)row.Cells[1].Value);
                var q = (from t1 in player_.ReportDB.report
                        join t2 in player_.ReportDB.participant
                          on t1.ID equals t2.ReportID
                        //join t4 in TravianLib.Utils.TravianData.troops
                        // on t3.UnitType equals t4.ID
                        //join t3 in player_.reportDB.unit
                        //on t2.ID equals t3.ParticipantID
                        where t2.TargetVillageC == selected.VillageID
                        //orderby t2.ID
                        orderby t1.Date descending
                        select new
                        {
                            Date = t1.Date,
                            Wood = t1.Wood,
                            Clay = t1.Clay,
                            Iron = t1.Iron,
                            Crop = t1.Crop,
                            Eff = (double)(t1.Wood + t1.Clay + t1.Iron + t1.Crop) * 100 /
                            (from r2 in player_.ReportDB.participant
                             join r3 in player_.ReportDB.unit
                                 on r2.ID equals r3.ParticipantID
                             where r2.ReportID == t1.ID && r2.Role
                             group r3 by r3.UnitType into g
                             select new
                             {
                                 Capacity = (from u in TravianLib.Utils.TravianData.troops
                                             where u.ID == g.Key
                                             select u.Capacity).SingleOrDefault(),
                                 Amount = g.Sum(j => j.Amount)
                             }).Sum(h => h.Capacity * h.Amount)
                        }).Where(b => !double.IsInfinity(b.Eff));
                        
                            //(from r2 in player_.reportDB.participant
                            // join r3 in player_.reportDB.unit
                            //     on r2.ID equals r3.ParticipantID
                            // join unitStats in TravianLib.Utils.TravianData.troops
                            // on r3.UnitType equals unitStats.ID
                            // where r2.ReportID == t1.ID && r2.Role && unitStats.ID == r3.UnitType
                            // group unitStats by r2.ReportID into g
                            // select (double)(C * g.Sum(f => f.Capacity))).SingleOrDefault() * 100).ToString("F")
                            //      Unit = t4.Name
               
          
                    BindingSource bs = new BindingSource();
                    bs.DataSource = q;
                    dataGridView2.AutoGenerateColumns = true;
                    dataGridView2.DataSource = bs;
                    dataGridView2.AutoResizeColumns();

             

                BindingSource bs2 = new BindingSource();
                bs2.DataSource = selected.Histories.OrderByDescending(c => c.Date);
                dataGridView3.AutoGenerateColumns = true;
                dataGridView3.DataSource = bs2;
                dataGridView3.AutoResizeColumns();

                lblName.Text = "Village: " + selected.Name;
try {
                    lblRace.Text = q.Count() == 0 ? "Sum: 0" : "Sum: " +  q.Sum(f => f.Clay +f.Wood + f.Crop + f.Iron)  + " Eff%: " + (q.Sum(f => f.Eff) / (double)q.Count()).ToString("F");                
}
                catch {
                    lblRace.Text = "Sum: 0";
                }

                if (dataGridView2.Columns.Count > 2)
                {
                    dataGridView2.Columns["Eff"].ValueType = typeof(System.Double);
                    dataGridView2.Columns["Eff"].DefaultCellStyle.Format = "F";
                }
                if (dataGridView3.Columns.Count > 0)
                {
                    dataGridView3.Columns["ID"].Visible = false;
                    dataGridView3.Columns["Village"].Visible = false;
                }
            }
        }
        private void SetPlusFeatures(object sender, EventArgs e)
        {
            vil.PlusProduction.wood = checkBoxWood.Checked;
            vil.PlusProduction.clay = checkBoxClay.Checked;
            vil.PlusProduction.iron = checkBoxIron.Checked;
            vil.PlusProduction.crop = checkBoxCrop.Checked;
        }
        private void button6_Click(object sender, EventArgs e)
        {
            vil.optimizeQueuev2();
            drawBuildings();
        }

        private void attackMapToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WindowsFormsApplication4.AttackMap am = new WindowsFormsApplication4.AttackMap();
            am.Show();
        }

        private void checkBoxSend_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxSend.Checked)
            {
                List<TimeSpan> result = vil.Barracks.Attack((int)this.numericUpDownSquadSize.Value);

                foreach (TimeSpan item in result)
                {
                    System.Windows.Forms.Timer newTimer = new System.Windows.Forms.Timer();
                    newTimer.Enabled = false;
                    timers_.Add(newTimer);
                    newTimer.Interval += (int)item.TotalMilliseconds * 2;
                    newTimer.Tick += new EventHandler(timer2_Tick);
                    newTimer.Enabled = true;
                }
            }
        }
    }
}
